package copyengine.scenes.viewport.impl
{
	import copyengine.scenes.viewport.ICEViewport;
	import copyengine.scenes.viewport.ICEViewportEventListener;
	import copyengine.scenes.viewport.ICEViewportWarp;
	import copyengine.utils.GeneralUtils;

	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class CEViewportWarpBasic implements ICEViewportWarp
	{
		/**
		 *Click事件触发的区域
		 */
		private static const CLICK_RESPOND_RANGE:int = 10;

		protected var viewport:ICEViewport;

		protected var viewportWarpContainer:Sprite;

		private var preMouseX:Number;
		private var preMouseY:Number;

		private var downMouseX:Number;
		private var downMouseY:Number;

		private var isViewportWarpPause:Boolean;

		private var allViewportClickEventListenerVector:Vector.<ICEViewportEventListener>;

		public function CEViewportWarpBasic()
		{
			viewportWarpContainer = new Sprite();
			allViewportClickEventListenerVector = new Vector.<ICEViewportEventListener>();
			isViewportWarpPause = false;
		}

		public final function setViewport(_viewport:ICEViewport):void
		{
			viewport = _viewport;
			addListener();
			doInitialzie();
		}

		protected function doInitialzie():void
		{
		}

		public final function dispose():void
		{
			removeListener();
			viewportWarpContainer = null;
			viewport = null;
		}

		public final function getViewportWarpContainer():DisplayObjectContainer
		{
			return viewportWarpContainer;
		}

		public final function pauseWarp():void
		{
			isViewportWarpPause = true;
		}

		public final function continueWarp():void
		{
			isViewportWarpPause = false;
		}

		public function addViewportClickEventListener(_listener:ICEViewportEventListener):void
		{
			allViewportClickEventListenerVector.indexOf(_listener) < 0 && allViewportClickEventListenerVector.push(_listener);
		}

		public function removeViewportClickEventListener(_listener:ICEViewportEventListener):void
		{
			GeneralUtils.removeElementFromArrayOrVector(_listener, allViewportClickEventListenerVector);
		}

		protected final function addListener():void
		{
			//could not add Mouse Up.Down Listener on warpContainer 
			//beacuse in that case other layer can not respond any mouse event.
			//only add Mouse Move Evnet on that layer beacuse , during mouse move not want any other layer respond mouse event
			GeneralUtils.addTargetEventListener(viewport.container, MouseEvent.ROLL_OUT, onMouseRollOut);
			GeneralUtils.addTargetEventListener(viewport.container, MouseEvent.MOUSE_DOWN, onMouseDown);
			GeneralUtils.addTargetEventListener(viewport.container, MouseEvent.MOUSE_UP, onMouseUp);
			GeneralUtils.addTargetEventListener(viewport.container, MouseEvent.MOUSE_MOVE, onUnPressedMouseMove);
		}

		protected final function removeListener():void
		{
			GeneralUtils.removeTargetEventListener(viewport.container, MouseEvent.ROLL_OUT, onMouseRollOut);
			GeneralUtils.removeTargetEventListener(viewport.container, MouseEvent.MOUSE_DOWN, onMouseDown);
			GeneralUtils.removeTargetEventListener(viewport.container, MouseEvent.MOUSE_UP, onMouseUp);
			GeneralUtils.removeTargetEventListener(viewportWarpContainer, MouseEvent.MOUSE_MOVE, onPressedMouseMove);
			GeneralUtils.removeTargetEventListener(viewport.container, MouseEvent.MOUSE_MOVE, onUnPressedMouseMove);
		}

		private function onMouseRollOut(e:MouseEvent):void
		{
			onMouseUp(e);
		}

		private function onMouseDown(e:MouseEvent):void
		{
			fillWarpContainer();

			downMouseX = preMouseX = e.stageX;
			downMouseY = preMouseY = e.stageY;

			GeneralUtils.addTargetEventListener(viewportWarpContainer, MouseEvent.MOUSE_MOVE, onPressedMouseMove);
			GeneralUtils.removeTargetEventListener(viewport.container, MouseEvent.MOUSE_MOVE, onUnPressedMouseMove);

			doOnMouseDown(e);
		}

		private function onMouseUp(e:MouseEvent):void
		{
			if (e.stageX < downMouseX + CLICK_RESPOND_RANGE
				&& e.stageX > downMouseX - CLICK_RESPOND_RANGE
				&& e.stageY < downMouseY + CLICK_RESPOND_RANGE
				&& e.stageY > downMouseY - CLICK_RESPOND_RANGE)
			{
				onMouseClick(e);
			}
			cleanWarpContainer();

			GeneralUtils.addTargetEventListener(viewport.container, MouseEvent.MOUSE_MOVE, onUnPressedMouseMove);
			GeneralUtils.removeTargetEventListener(viewportWarpContainer, MouseEvent.MOUSE_MOVE, onPressedMouseMove);
		}

		private function onPressedMouseMove(e:MouseEvent):void
		{
			//ForceTutorial中Pause 不能移动
			if (isViewportWarpPause)
			{
				return;
			}

			var offsetX:Number = e.stageX - preMouseX;
			var offsetY:Number = e.stageY - preMouseY;

			tryToMoveTo(viewport.currentPosX - offsetX, viewport.currentPosY - offsetY, viewport.viewportWidth, viewport.viewportHeight);

			preMouseX = e.stageX;
			preMouseY = e.stageY;

			doOnPressedMouseMove(e);
		}

		private function onUnPressedMouseMove(e:MouseEvent):void
		{
			for each (var listener:ICEViewportEventListener in allViewportClickEventListenerVector)
			{
				listener.onMouseMoveInViewport(viewport.currentPosX + e.stageX, viewport.currentPosY + e.stageY, e.stageX, e.stageY);
			}
			doOnUnPressedMouseMove(e);
		}

		private function onMouseClick(e:MouseEvent):void
		{
			for each (var listener:ICEViewportEventListener in allViewportClickEventListenerVector)
			{
				listener.onMouseClickInViewport(viewport.currentPosX + e.stageX, viewport.currentPosY + e.stageY, e.stageX, e.stageY);
			}
			doOnMouseClick(e);
		}

		protected final function fillWarpContainer():void
		{
			var g:Graphics = viewportWarpContainer.graphics;
			g.beginFill(0, 0);
			g.drawRect(0, 0, viewport.viewportWidth, viewport.viewportHeight);
			g.endFill();
		}

		protected final function cleanWarpContainer():void
		{
			viewportWarpContainer.graphics.clear();
		}

		//===================
		//==Child 可以 Override的方法
		//====================

		/**
		 * 本类的移动不做任何的Bound范围判断直接移动视口，如果子类需要
		 * 进行Bound范围判断需要Override这个函数并且
		 * 不调用Super方法
		 */
		protected function tryToMoveTo(_posX:int, _posY:int, _viewportWidth:int, _viewportHeight:int):void
		{
			viewport.moveTo(_posX, _posY);
		}

		protected function doOnMouseDown(e:MouseEvent):void
		{
		}

		protected function doOnMouseClick(e:MouseEvent):void
		{
		}

		protected function doOnPressedMouseMove(e:MouseEvent):void
		{
		}

		protected function doOnUnPressedMouseMove(e:MouseEvent):void
		{
		}


	}
}
